package com.yaodian100.ec.order.entity;

/**
 * @author jinwei.lin
 *
 */
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import com.yaodian100.core.common.entity.BaseEntity;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.entity.Specification;
import com.yaodian100.ec.shelf.entity.Shelf;
import com.yaodian100.ec.shopping.entity.CartOrderProduct;

@Entity
@Table(name = "EC_ORDER_PRODUCT", uniqueConstraints = { @UniqueConstraint(columnNames = { "order_id", "prod_seq" }) })
public class OrderProduct extends BaseEntity {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6173275198766493791L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO, generator = "seq_ec_order_prod")
	@SequenceGenerator(name = "seq_ec_order_prod", sequenceName = "seq_ec_order_prod")
	@Column(name = "order_prod_id")
	private Long orderProdId;

	@Column(name = "order_id", length = 13, insertable = false, updatable = false)
	private String orderId;
	/** order */
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "order_id", nullable = false)
	private Orders order;

	@Column(name = "prod_seq", nullable = false)
	private int prodSeq;

	@Column(name = "prod_id", length = 10, nullable = false, updatable = false)
	private String prodId;

	@Column(name = "prod_spec_id", length = 10, nullable = false, updatable = false)
	private String prodSpecId;

	@Column(name = "prod_name", length = 500, nullable = false)
	private String prodName;

	@Column(name = "prod_spec_name", length = 300, nullable = false)
	private String prodSpecName;

	@Column(name = "prod_tp", length = 5, nullable = false)
	private String prodTp;

	/** logisticTp */
	@Column(name = "logistic_tp", length = 5, nullable = false)
	private String logisticTp = " ";

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "logistic_send_dt")
	private Date logisticSendDt;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "logistic_final_dt")
	private Date logisticFinalDt;

	@Column(name = "logistic_st", length = 5, nullable = false)
	private String logisticSt = " ";

	@Column(name = "logistic_no", length = 64)
	private String logisticNo = " ";

	@Column(name = "logistic_company", length = 15)
	private String logisticCompany = " ";

	@Column(name = "return_qty")
	private int returnQty;

	/** returnAmount */
	@Column(name = "return_amount", columnDefinition = "numeric(10,2)")
	private BigDecimal returnAmount = BigDecimal.ZERO;

	@Column(name = "ec_cost", columnDefinition = "numeric(10,2)")
	private BigDecimal ecCost = BigDecimal.ZERO;

	@Column(name = "epr_cost", columnDefinition = "numeric(10,2)")
	private BigDecimal erpCost = BigDecimal.ZERO;

	@Column(name = "unit_price", columnDefinition = "numeric(10,2)")
	private BigDecimal unitPrice = BigDecimal.ZERO;

	@Column(name = "qty")
	private int qty = 0;

	/** totalPrice */
	@Column(name = "total_price", columnDefinition = "numeric(10,2)")
	private BigDecimal totalPrice = BigDecimal.ZERO;

	/** amount */
	@Column(name = "amount", columnDefinition = "numeric(10,2)")
	private BigDecimal amount = BigDecimal.ZERO;

	/** discount, 折扣總計 */
	@Column(name = "discount", columnDefinition = "numeric(10,2)")
	private BigDecimal discount = BigDecimal.ZERO;

	/** coupon, 使用 coupon 的面額 */
	@Column(name = "coupon", columnDefinition = "numeric(10,2)")
	private BigDecimal coupon = BigDecimal.ZERO;

	@Column(name = "return_coupon", columnDefinition = "numeric(10,2)")
	private BigDecimal returnCoupon = BigDecimal.ZERO;

	@Column(name = "couponId", length = 40)
	private String couponId;

	@Column(name = "couponitem_id", length = 40)
	private String couponItemId;

	@Column(name = "category_path", length = 80, nullable = false)
	private String categoryPath;

	@Column(name = "pm_id", length = 20)
	private String pmId;

	@Column(name = "pm_group", length = 20)
	private String pmGroup;

	@Column(name = "is_campaign")
	private boolean isCampaign = false;

	@Column(name = "is_return")
	private boolean isReturn = false;

	@Column(name = "is_change")
	private boolean isChange = false;

	@Column(name = "campaign_id", length = 40, updatable = false)
	private String campaignId = " ";

	@Column(name = "campaign_name", length = 100)
	private String campaignName;

	@OneToMany(mappedBy = "orderProd")
	@LazyCollection(LazyCollectionOption.FALSE)
	@OrderBy("detailSeq asc")
	@Cascade( { CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN })
	private List<OrderProductDetail> orderProductDetail;
	/*
	 * 0:一般状态 1:退货 2:换货 3:取消
	 */
	@Column(name = "prod_status")
	private Integer prodStatus = 0;
	@Column(name = "logistic_remark", length = 255)
	private String logisticRemark;

	@Column(name = "logistic_ref_num", length = 64)
	private String logisticRefNum;
	@Column(name = "logistic_company2", length = 15)
	private String logisticCompany2;

	/**
	 * 退换货条件
	 */
	@Column(name = "RETURN_RULE", length = 5)
	private String returnRule = "07_15";

	/** cash */
	@Column(name = "cash", columnDefinition = "numeric(10,2)")
	private BigDecimal cash = BigDecimal.ZERO;

	/**
	 * 记录该商品礼品卡使用比例(扣除运费，前几笔商品采用小数点第一位后无条件舍去的方式计算，最后一笔商品用减的)
	 */
	@Column(name = "GIFTCARD_BALANCE", columnDefinition = "NUMERIC(10, 2)")
	private BigDecimal giftcardBalance = BigDecimal.ZERO;

	@Column(name = "bonus", columnDefinition = "numeric(10,2)")
	private BigDecimal bonus = BigDecimal.ZERO;

	/** shipfare, 運費 */
	@Column(name = "shipfare", columnDefinition = "numeric(10,2)")
	private BigDecimal shipfare = BigDecimal.ZERO;

	@Column(name = "my_wallet", columnDefinition = "numeric(10,2)")
	private BigDecimal myWallet = BigDecimal.ZERO;

	@Column(name = "must_pay", columnDefinition = "numeric(10,2)")
	private BigDecimal mustPay = BigDecimal.ZERO;

	/** COD手續費 */
	@Column(name = "COD_FEE", columnDefinition = "numeric(10,2)")
	private BigDecimal codFee = BigDecimal.ZERO;

	@Column(name = "INSTALLMENT_FEE", columnDefinition = "numeric(10,2)")
	private BigDecimal installmentFee = BigDecimal.ZERO;

	/**
	 * @return the logisticCompany2
	 */
	public String getLogisticCompany2() {
		return logisticCompany2;
	}

	/**
	 * @param logisticCompany2 the logisticCompany2 to set
	 */
	public void setLogisticCompany2(String logisticCompany2) {
		this.logisticCompany2 = logisticCompany2;
	}

	/** default constructor */
	public OrderProduct() {
		super();
	}

	public OrderProduct(CartOrderProduct cop) {
		super();
		this.unitPrice = cop.getUnitPrice();
		this.categoryPath = cop.getCategoryPath();
		this.prodId = cop.getProdId();
		this.pmId = cop.getPmId();
		this.pmGroup = cop.getPmGroup();
		this.prodName = cop.getProdName();
		this.prodSpecId = cop.getProdSpecId();
		this.prodSpecName = cop.getProdSpecName();
		if ("6N".equals(cop.getProdTp())) {
			this.prodTp = "6";
		} else {
			this.prodTp = cop.getProdTp();
		}
		this.qty = cop.getQty();
		this.unitPrice = cop.getUnitPrice();
		this.totalPrice = cop.getTotalPrice();
		this.discount = cop.getDiscount();

		this.campaignId = cop.getCampaignId();
		this.campaignName = cop.getCampaignName();

		this.amount = this.totalPrice.subtract(this.coupon).subtract(this.discount);
	}

	public OrderProduct(Product prod, Specification spec, String categoryPath, Shelf shelf) {
		super();
		if (StringUtils.isBlank(categoryPath)) {
			this.categoryPath = prod.getMainCategoryPath();
		} else {
			this.categoryPath = categoryPath;
		}
		this.prodId = prod.getProductId();
		this.pmId = prod.getPmID();
		this.pmGroup = prod.getOrganizationPath();
		this.prodName = prod.getProductName();
		this.ecCost = prod.getProductCost();
		this.prodSpecId = spec.getSpecificationId().toString();
		this.prodSpecName = spec.getSpecificationName();
		if (shelf.getShelfPrice().compareTo(BigDecimal.ZERO) == 0) {
			this.prodTp = "2";
		} else {
			this.prodTp = "0";
		}
		this.qty = 1;
		this.unitPrice = shelf.getShelfPrice();
		this.totalPrice = shelf.getShelfPrice();
		this.discount = BigDecimal.ZERO;

		this.amount = this.totalPrice.subtract(this.coupon).subtract(this.discount);
	}

	/**
	 * @return the order
	 */
	public Orders getOrder() {
		return order;
	}

	/**
	 * @param order the order to set
	 */
	public void setOrder(Orders order) {
		this.order = order;
	}

	public BigDecimal getAmount() {
		amount = totalPrice.subtract(coupon).subtract(discount);
		return amount;
	}

	public String getCampaignId() {
		return campaignId;
	}

	public String getCampaignName() {
		return campaignName;
	}

	public String getCategoryPath() {
		return categoryPath;
	}

	public BigDecimal getCoupon() {
		return coupon;
	}

	public String getCouponId() {
		return couponId;
	}

	public BigDecimal getDiscount() {
		return discount;
	}

	public BigDecimal getEcCost() {
		return ecCost;
	}

	public BigDecimal getErpCost() {
		return erpCost;
	}

	public String getLogisticCompany() {
		return logisticCompany;
	}

	public Date getLogisticFinalDt() {
		return logisticFinalDt;
	}

	public String getLogisticNo() {
		return logisticNo;
	}

	/**
	 * @return the logisticRefNum
	 */
	public String getLogisticRefNum() {
		return logisticRefNum;
	}

	/**
	 * @return the logisticRemark
	 */
	public String getLogisticRemark() {
		return logisticRemark;
	}

	public Date getLogisticSendDt() {
		return logisticSendDt;
	}

	public String getLogisticSt() {
		return logisticSt;
	}

	public String getLogisticTp() {
		return logisticTp;
	}

	public String getOrderId() {
		return orderId;
	}

	public Long getOrderProdId() {
		return orderProdId;
	}

	public List<OrderProductDetail> getOrderProductDetail() {
		if (orderProductDetail == null) {
			orderProductDetail = new ArrayList();
		}
		return orderProductDetail;
	}

	public OrderProduct addDetail(OrderProductDetail opd) {
		getOrderProductDetail().add(opd);
		opd.setOrderProd(this);
		opd.setProdSeq(getProdSeq());
		opd.setOrder(order);
		return this;
	}

	public String getPmGroup() {
		return pmGroup;
	}

	public String getPmId() {
		return pmId;
	}

	public String getProdId() {
		return prodId;
	}

	public String getProdName() {
		return prodName;
	}

	public int getProdSeq() {
		return prodSeq;
	}

	public String getProdSpecId() {
		return prodSpecId;
	}

	public String getProdSpecName() {
		return prodSpecName;
	}

	/**
	 * @return the prodStatus
	 */
	public Integer getProdStatus() {
		return prodStatus;
	}

	public String getProdTp() {
		return prodTp;
	}

	public int getProductCount() {
		int prodCount = 0;
		for (OrderProductDetail detail : orderProductDetail) {
			if (!detail.getDetailTp().equals("2")) {
				prodCount++;
			}
		}
		return prodCount;
	}

	public int getQty() {
		return qty;
	}

	public BigDecimal getReturnAmount() {
		return returnAmount;
	}

	public BigDecimal getReturnCoupon() {
		return returnCoupon;
	}

	public int getReturnQty() {
		return returnQty;
	}

	public BigDecimal getTotalPrice() {
		return totalPrice;
	}

	public BigDecimal getUnitPrice() {
		return unitPrice;
	}

	public boolean isCampaign() {
		return isCampaign;
	}

	public boolean isChange() {
		return isChange;
	}

	public boolean isReturn() {
		return isReturn;
	}

	public void setCampaign(boolean isCampaign) {
		this.isCampaign = isCampaign;
	}

	public void setCampaignId(String campaignId) {
		this.campaignId = campaignId;
	}

	public void setCampaignName(String campaignName) {
		this.campaignName = campaignName;
	}

	public void setCategoryPath(String categoryPath) {
		this.categoryPath = categoryPath;
	}

	public void setChange(boolean isChange) {
		this.isChange = isChange;
	}

	public void setCoupon(BigDecimal coupon) {
		this.coupon = coupon;
		this.amount = totalPrice.subtract(coupon).subtract(discount);
	}

	public void setCouponId(String couponId) {
		this.couponId = couponId;
	}

	public void setDiscount(BigDecimal discount) {
		this.discount = discount;
		this.amount = totalPrice.subtract(coupon).subtract(discount);
	}

	public void setEcCost(BigDecimal ecCost) {
		this.ecCost = ecCost;
	}

	public void setErpCost(BigDecimal erpCost) {
		this.erpCost = erpCost;
	}

	public void setLogisticCompany(String logisticCompany) {
		this.logisticCompany = logisticCompany;
	}

	public void setLogisticFinalDt(Date logisticFinalDt) {
		this.logisticFinalDt = logisticFinalDt;
	}

	public void setLogisticNo(String logisticNo) {
		this.logisticNo = logisticNo;
	}

	/**
	 * @param logisticRefNum the logisticRefNum to set
	 */
	public void setLogisticRefNum(String logisticRefNum) {
		this.logisticRefNum = logisticRefNum;
	}

	/**
	 * @param logisticRemark the logisticRemark to set
	 */
	public void setLogisticRemark(String logisticRemark) {
		this.logisticRemark = logisticRemark;
	}

	public void setLogisticSendDt(Date logisticSendDt) {
		this.logisticSendDt = logisticSendDt;
	}

	public void setLogisticSt(String logisticSt) {
		this.logisticSt = logisticSt;
	}

	public void setLogisticTp(String logisticTp) {
		this.logisticTp = logisticTp;
	}

	public void setOrderId(String orderId) {
		this.orderId = orderId;
	}

	public void setOrderProdId(Long orderProdId) {
		this.orderProdId = orderProdId;
	}

	public void setOrderProductDetail(List<OrderProductDetail> orderProductDetail) {
		this.orderProductDetail = orderProductDetail;
	}

	public void setPmGroup(String pmGroup) {
		this.pmGroup = pmGroup;
	}

	public void setPmId(String pmId) {
		this.pmId = pmId;
	}

	public void setProdId(String prodId) {
		this.prodId = prodId;
	}

	public void setProdName(String prodName) {
		this.prodName = prodName;
	}

	public void setProdSeq(int prodSeq) {
		this.prodSeq = prodSeq;
	}

	public void setProdSpecId(String prodSpecId) {
		this.prodSpecId = prodSpecId;
	}

	public void setProdSpecName(String prodSpecName) {
		this.prodSpecName = prodSpecName;
	}

	/**
	 * @param prodStatus the prodStatus to set
	 */
	public void setProdStatus(Integer prodStatus) {
		this.prodStatus = prodStatus;
	}

	public void setProdTp(String prodTp) {
		this.prodTp = prodTp;
	}

	public void setQty(int qty) {
		this.qty = qty;
	}

	public void setReturn(boolean isReturn) {
		this.isReturn = isReturn;
	}

	public void setReturnAmount(BigDecimal returnAmount) {
		this.returnAmount = returnAmount;
	}

	public void setReturnCoupon(BigDecimal returnCoupon) {
		this.returnCoupon = returnCoupon;
	}

	public void setReturnQty(int returnQty) {
		this.returnQty = returnQty;
	}

	public void setTotalPrice(BigDecimal totalPrice) {
		this.totalPrice = totalPrice;
		this.amount = totalPrice.subtract(coupon).subtract(discount);
	}

	public void setUnitPrice(BigDecimal unitPrice) {
		this.unitPrice = unitPrice;
	}

	/**
	 * @return the couponItemId
	 */
	public String getCouponItemId() {
		return couponItemId;
	}

	/**
	 * @param couponItemId the couponItemId to set
	 */
	public void setCouponItemId(String couponItemId) {
		this.couponItemId = couponItemId;
	}

	/**
	 * @return the applyCampaigns
	 */
	@Transient
	public List<ApplyCampaign> getApplyCampaigns() {
		List<ApplyCampaign> applyCampaigns = new ArrayList<ApplyCampaign>();
		for (ApplyCampaign ac : order.getApplyCampaigns()) {
			if ((ac != null) && (ac.getApplyProductIds() != null)) {
				if (ac.getApplyProductIds().contains(prodId)) {
					applyCampaigns.add(ac);
				}
			}
		}
		return applyCampaigns;
	}

	public String getReturnRule() {
		// 相容於舊訂單資料，回傳預設值
		if ((returnRule == null) || "".equals(returnRule)) {
			return "07_15";
		} else {
			return returnRule;
		}
	}

	public void setReturnRule(String returnRule) {
		this.returnRule = returnRule;
	}

	public BigDecimal getGiftcardBalance() {
		return giftcardBalance;
	}

	public void setGiftcardBalance(BigDecimal giftcardBalance) {
		this.giftcardBalance = giftcardBalance;
	}

	public BigDecimal getBonus() {
		return bonus;
	}

	public void setBonus(BigDecimal bonus) {
		this.bonus = bonus;
	}

	public BigDecimal getShipfare() {
		return shipfare;
	}

	public BigDecimal getMyWallet() {
		return myWallet;
	}

	public void setShipfare(BigDecimal shipfare) {
		this.shipfare = shipfare;
	}

	public void setMyWallet(BigDecimal myWallet) {
		this.myWallet = myWallet;
	}

	public BigDecimal getMustPay() {
		return mustPay;
	}

	public void setMustPay(BigDecimal mustPay) {
		this.mustPay = mustPay;
	}

	public BigDecimal getCodFee() {
		return codFee;
	}

	public BigDecimal getInstallmentFee() {
		return installmentFee;
	}

	public void setCodFee(BigDecimal codFee) {
		this.codFee = codFee;
	}

	public void setInstallmentFee(BigDecimal installmentFee) {
		this.installmentFee = installmentFee;
	}

	public BigDecimal getCash() {
		return cash;
	}

	public void setCash(BigDecimal cash) {
		this.cash = cash;
	}
}
